1   /*
2    * Copyright (C) 2008 The Android Open Source Project
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.android.launcher;
18  
19  import android.content.BroadcastReceiver;
20  import android.content.Context;
21  import android.content.Intent;
22  import android.content.ContentResolver;
23  import android.database.Cursor;
24  import android.widget.Toast;
25  
26  public class InstallShortcutReceiver extends BroadcastReceiver {
27      private static final String ACTION_INSTALL_SHORTCUT =
28              "com.android.launcher.action.INSTALL_SHORTCUT";
29  
30      private final int[] mCoordinates = new int[2];
31  
32      public void onReceive(Context context, Intent data) {
33          if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
34              return;
35          }
36  
37          int screen = Launcher.getScreen();
38  
39          if (!installShortcut(context, data, screen)) {
40              // The target screen is full, let's try the other screens
41              for (int i = 0; i < Launcher.SCREEN_COUNT; i++) {
42                  if (i != screen && installShortcut(context, data, i)) break;
43              }
44          }
45      }
46  
47      private boolean installShortcut(Context context, Intent data, int screen) {
48          String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
49  
50          if (findEmptyCell(context, mCoordinates, screen)) {
51              CellLayout.CellInfo cell = new CellLayout.CellInfo();
52              cell.cellX = mCoordinates[0];
53              cell.cellY = mCoordinates[1];
54              cell.screen = screen;
55  
56              Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
57  
58              if (intent.getAction() == null) {
59                  intent.setAction(Intent.ACTION_VIEW);
60              }
61  
62              // By default, we allow for duplicate entries (located in
63              // different places)
64              boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
65              if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {
66                  Launcher.addShortcut(context, data, cell, true);
67                  Toast.makeText(context, context.getString(R.string.shortcut_installed, name),
68                          Toast.LENGTH_SHORT).show();
69              } else {
70                  Toast.makeText(context, context.getString(R.string.shortcut_duplicate, name),
71                          Toast.LENGTH_SHORT).show();
72              }
73  
74              return true;
75          } else {
76              Toast.makeText(context, context.getString(R.string.out_of_space),
77                      Toast.LENGTH_SHORT).show();
78          }
79  
80          return false;
81      }
82  
83      private static boolean findEmptyCell(Context context, int[] xy, int screen) {
84          final int xCount = Launcher.NUMBER_CELLS_X;
85          final int yCount = Launcher.NUMBER_CELLS_Y;
86  
87          boolean[][] occupied = new boolean[xCount][yCount];
88  
89          final ContentResolver cr = context.getContentResolver();
90          Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
91              new String[] { LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
92                      LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY },
93              LauncherSettings.Favorites.SCREEN + "=?",
94              new String[] { String.valueOf(screen) }, null);
95  
96          final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
97          final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
98          final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
99          final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
100 
101         try {
102             while (c.moveToNext()) {
103                 int cellX = c.getInt(cellXIndex);
104                 int cellY = c.getInt(cellYIndex);
105                 int spanX = c.getInt(spanXIndex);
106                 int spanY = c.getInt(spanYIndex);
107 
108                 for (int x = cellX; x < cellX + spanX && x < xCount; x++) {
109                     for (int y = cellY; y < cellY + spanY && y < yCount; y++) {
110                         occupied[x][y] = true;
111                     }
112                 }
113             }
114         } catch (Exception e) {
115             return false;
116         } finally {
117             c.close();
118         }
119 
120         return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);
121     }
122 }